﻿using UnityEngine;
using System.Collections;
using EnemyClasses;
using KeyBindings;

namespace PlayerClasses
{
	/// <summary>
	/// Player death to detect winning or losing.
	/// </summary>
	public delegate void PlayerDeath ();
	// Require these components when using this script
	[RequireComponent(typeof(Animator))]
	[RequireComponent(typeof(CapsuleCollider))]
	[RequireComponent(typeof(Rigidbody))]
	public class PlayerController : MonoBehaviour
	{
		public static Transform playerPos;
		public static event PlayerDeath PlayerDeathEvent;
		public float animSpeed = 1.5f;				// a public setting for overall animator animation speed
			
		private Animator anim;							// a reference to the animator on the character
		private AnimatorStateInfo currentBaseState;			// a reference to the current state of the animator, used for base layer
		private AnimatorStateInfo layer2CurrentState;	// a reference to the current state of the animator, used for layer 2
		private BoxCollider col;					// a reference to the capsule collider of the character
		
		//static int locoState = Animator.StringToHash ("Base Layer.Locomotion");			// these integers are references to our animator's states
		//static int jumpState = Animator.StringToHash ("Base Layer.Jump");				// and are used to check state for various actions to occur

		public AudioSource mySound;

		private static PlayerController player;
		float time = 0;
		bool idleSearch = false;
		bool idle = false;
		bool jump = false;
		bool attack = false;
		public static bool death = false;
		public int Health = 100;
		public float speed;
		private float h;
		private float v;
		private bool underAttack;

		void Start ()
		{
			// initialising reference variables
			anim = GetComponent<Animator> ();					  
			col = GetComponent<BoxCollider> ();	

			playerPos = transform;

			//enemy = GameObject.Find("Enemy").transform;	
			if (anim.layerCount == 2) {
				anim.SetLayerWeight (1, 1);
			}

			h = 0;
			v = 0;
			underAttack = false;
			player = this;
			Screen.showCursor = false;
		}
	
		void Update ()
		{		
			//Don not move and animate locomotion unless alive.
			if (!jump && !attack && !death) {
				if (Input.GetKey (KeyCode.Escape)) {
					Application.Quit ();
				}
			
				if (KeyManager.Instance ["MoveForward"]) {
					idleSearch = false;
					time = 0;
					v = 1f;
				} else if (KeyManager.Instance ["MoveBack"]) {
					idleSearch = false;
					time = 0;
					v = -1f;
				} else {
					if (time >= 10) {
						idleSearch = true;
					}
					v = 0;
				}

				if (KeyManager.Instance ["StrafeLeft"]) {
					idleSearch = false;
					time = 0;
					h = -1f;
				} else if (KeyManager.Instance ["StrafeRight"]) {
					idleSearch = false;
					time = 0;
					h = 1f;
				} else {
					if (time >= 10) {
						idleSearch = true;
					}
					h = 0;
				}
			}

			//Jump animation
			if (KeyManager.Instance ["Jump"] && !jump && !attack && !death) {
				jump = true;
				time = 0;
				h = 0;
				v = 0;
			} else {
				//Jump attack
				if ((KeyManager.Instance ["Attack"] || Input.GetMouseButton (0)) && !attack && !death) {
					Input.GetMouseButtonUp (0);
					attack = true;
					time = 0;
					mySound.Play ();
				}

				if (time >= 0.52f && jump && attack) {
					attack = false;
					jump = false;
				}

				if (time >= 1.2f) {
					jump = false;
				}
			}

			//Attack animation
			if ((KeyManager.Instance ["Attack"] || Input.GetMouseButton (0)) && !jump && !attack && !death) {
				Input.GetMouseButtonUp (0);
				attack = true;
				mySound.Play ();
				time = 0;
				h = 0;
				v = 0;
			} else {
				if (time >= 0.56f) {
					attack = false;
				}
			}
		}
	
	
		void FixedUpdate ()
		{
			//If the player is not dead they can move.
			if (!death) {
				float moveX = h * speed * Time.deltaTime;
				float moveZ = v * speed * Time.deltaTime;

				transform.Translate (moveX, 0.0f, moveZ);
			}
		
			anim.SetFloat ("Speed", v);							// set our animator's float parameter 'Speed' equal to the vertical input axis				
			anim.SetFloat ("Direction", h); 						// set our animator's float parameter 'Direction' equal to the horizontal input axis		
			anim.SetFloat ("Time", time);
			anim.SetBool ("IdleSearch", idleSearch);
			anim.SetBool ("Idle", idle);
			anim.SetBool ("Jump", jump);
			anim.SetBool ("Attack", attack);
			anim.SetBool ("Death", death);
			anim.speed = animSpeed;								// set the speed of our animator to the public variable 'animSpeed'
			currentBaseState = anim.GetCurrentAnimatorStateInfo (0);	// set our currentState variable to the current state of the Base Layer (0) of animation
		
			if (anim.layerCount == 2)		
				layer2CurrentState = anim.GetCurrentAnimatorStateInfo (1);	// set our layer2CurrentState variable to the current state of the second Layer (1) of animation
		
		
			//TIME
			if (time < 10f) {
				time += Time.deltaTime;
			} else {
				time = 0;
			}
		}

		void OnTriggerStay (Collider other)
		{
			if (attack && other.tag == "Enemy") {
				Enemy em = (Enemy)other.GetComponent ("Enemy");
				em.Alive = false;
			}

			if (attack && other.tag == "Boss") {
				Boss boss = (Boss)other.GetComponent ("Boss");
				boss.Damage ();
			}
		}

		/// <summary>
		/// If the is under attack he will take damage.
		/// </summary>
		/// <param name="d">D.</param>
		public static void damage (int d)
		{
			if (!player.underAttack) {
				player.Health -= d;
				
				if (player.Health <= 0) {
					player.jump = false;
					player.attack = false;
					death = true;
					player.time = 0;
					player.h = 0;
					player.v = 0;
					if (PlayerDeathEvent != null) {
						PlayerDeathEvent ();
					}
				}
				
				player.Invoke ("doDamage", 0.8f);
				player.underAttack = true;
			}
		}

		/// <summary>
		/// Sets whether the player is under attack or not.
		/// </summary>
		private void doDamage ()
		{
			underAttack = false;
		}
	}
}